/**
 ******************************************************************************
 * @file           : bsp_tim_base.c
 * @brief          : Basic Timer Driver Implementation
 ******************************************************************************
 * @attention
 *
 * 基本定时器驱动程序实现
 * 支持TIM6和TIM7的定时中断功能
 * 提供周期性定时中断、DAC触发等功能
 *
 * 适配平台：STM32F1xx
 *
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "./BSP/TIMER/bsp_tim_base.h"

/* ============================================================================ */
/*                          日志配置（用户可修改）                               */
/* ============================================================================ */
/* 日志后端选择：1=EasyLogger, 2=printf, 0=关闭 */
#define BASE_TIM_USE_LOG     0

#if (BASE_TIM_USE_LOG == 1)
    /* 使用EasyLogger */
    #ifndef LOG_TAG
        #define LOG_TAG    "TIM_BASE"
    #endif
    #include "elog.h"
    
#elif (BASE_TIM_USE_LOG == 2)
    /* 使用printf */
    #include <stdio.h>
    #define log_i(fmt, ...)     printf(fmt "\r\n", ##__VA_ARGS__)
    #define log_w(fmt, ...)     printf("[WARN] " fmt "\r\n", ##__VA_ARGS__)
    #define log_e(fmt, ...)     printf("[ERROR] " fmt "\r\n", ##__VA_ARGS__)
    #define log_d(fmt, ...)     printf("[DEBUG] " fmt "\r\n", ##__VA_ARGS__)
    
#else
    /* 关闭日志 */
    #define log_i(fmt, ...)
    #define log_w(fmt, ...)
    #define log_e(fmt, ...)
    #define log_d(fmt, ...)
#endif

/* Private includes ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

#ifdef BASE_TIM_USE_TIM6
static TIM_HandleTypeDef s_tim6_handle = {0};                   /*!< TIM6句柄 */
static void (*s_tim6_callback)(void) = NULL;                    /*!< TIM6回调函数 */
static uint8_t s_tim6_initialized = 0;                          /*!< TIM6初始化标志 */
#endif

#ifdef BASE_TIM_USE_TIM7
static TIM_HandleTypeDef s_tim7_handle = {0};                   /*!< TIM7句柄 */
static void (*s_tim7_callback)(void) = NULL;                    /*!< TIM7回调函数 */
static uint8_t s_tim7_initialized = 0;                          /*!< TIM7初始化标志 */
#endif

/* Private function prototypes -----------------------------------------------*/
static TIM_HandleTypeDef* tim_base_get_handle(BASE_TIM_ID_e tim_id);
static uint8_t* tim_base_get_init_flag(BASE_TIM_ID_e tim_id);

/* Private functions ---------------------------------------------------------*/

/**
 * @brief       获取定时器句柄
 *
 * @param[in]   tim_id 定时器ID
 *
 * @retval      定时器句柄指针
 */
static TIM_HandleTypeDef* tim_base_get_handle(BASE_TIM_ID_e tim_id)
{
#ifdef BASE_TIM_USE_TIM6
    if (tim_id == BASE_TIM_ID_TIM6)
    {
        return &s_tim6_handle;
    }
#endif

#ifdef BASE_TIM_USE_TIM7
    if (tim_id == BASE_TIM_ID_TIM7)
    {
        return &s_tim7_handle;
    }
#endif

    return NULL;
}

/**
 * @brief       获取初始化标志
 *
 * @param[in]   tim_id 定时器ID
 *
 * @retval      初始化标志指针
 */
static uint8_t* tim_base_get_init_flag(BASE_TIM_ID_e tim_id)
{
#ifdef BASE_TIM_USE_TIM6
    if (tim_id == BASE_TIM_ID_TIM6)
    {
        return &s_tim6_initialized;
    }
#endif

#ifdef BASE_TIM_USE_TIM7
    if (tim_id == BASE_TIM_ID_TIM7)
    {
        return &s_tim7_initialized;
    }
#endif

    return NULL;
}

/* Exported functions --------------------------------------------------------*/

/**
 * @brief       基本定时器初始化
 *
 * @param[in]   tim_id 定时器ID
 * @param[in]   period_ms 定时周期（ms）
 *
 * @retval      无
 *
 * @note        TIM6/7时钟 = 36MHz（APB1）× 2 = 72MHz
 * @note        定时周期 = (psc+1) × (arr+1) / 72MHz
 */
void tim_base_init(BASE_TIM_ID_e tim_id, uint16_t period_ms)
{
    TIM_HandleTypeDef *handle;
    uint8_t *init_flag;
    uint32_t prescaler;
    uint32_t period;
    HAL_StatusTypeDef hal_status;
    
    if (tim_id >= BASE_TIM_ID_MAX)
    {
        log_e("Invalid timer ID: %d", tim_id);
        return;
    }
    
    handle = tim_base_get_handle(tim_id);
    init_flag = tim_base_get_init_flag(tim_id);
    
    if (handle == NULL || init_flag == NULL)
    {
        log_e("TIM%d not enabled in config", tim_id == BASE_TIM_ID_TIM6 ? 6 : 7);
        return;
    }
    
    if (*init_flag)
    {
        log_w("TIM%d already initialized", tim_id == BASE_TIM_ID_TIM6 ? 6 : 7);
        return;
    }
    
    /* 参数检查 */
    if (period_ms == 0)
    {
        log_w("period_ms=0, set to 1ms");
        period_ms = 1;
    }
    
    log_i("TIM%d Init: period=%d ms", tim_id == BASE_TIM_ID_TIM6 ? 6 : 7, period_ms);
    
    /*
     * 计算分频和周期值
     * TIM6/7时钟 = 72MHz
     * 目标：period_ms = (psc+1) × (arr+1) / 72000000 × 1000
     * 
     * 策略：psc=7199，则计数频率=72MHz/7200=10kHz（每0.1ms计数1次）
     * 则arr = period_ms × 10 - 1
     */
    prescaler = 7199;  /* 72MHz / 7200 = 10kHz */
    period = period_ms * 10 - 1;  /* 0.1ms × 10 = 1ms */
    
    /* 限制period范围（16位定时器） */
    if (period > 65535)
    {
        period = 65535;
    }
    
    /* 配置定时器 */
    if (tim_id == BASE_TIM_ID_TIM6)
    {
#ifdef BASE_TIM_USE_TIM6
        /* 使能TIM6时钟 */
        __HAL_RCC_TIM6_CLK_ENABLE();
        
        handle->Instance = TIM6;
        
        /* 配置中断 */
        HAL_NVIC_SetPriority(TIM6_DAC_IRQn, TIM6_PRIORITY, 0);
        HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
#endif
    }
    else if (tim_id == BASE_TIM_ID_TIM7)
    {
#ifdef BASE_TIM_USE_TIM7
        /* 使能TIM7时钟 */
        __HAL_RCC_TIM7_CLK_ENABLE();
        
        handle->Instance = TIM7;
        
        /* 配置中断 */
        HAL_NVIC_SetPriority(TIM7_IRQn, TIM7_PRIORITY, 0);
        HAL_NVIC_EnableIRQ(TIM7_IRQn);
#endif
    }
    
    /* 通用配置 */
    handle->Init.Prescaler = prescaler;
    handle->Init.CounterMode = TIM_COUNTERMODE_UP;
    handle->Init.Period = period;
    handle->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    
    hal_status = HAL_TIM_Base_Init(handle);
    if (hal_status != HAL_OK)
    {
        log_e("HAL_TIM_Base_Init failed: %d", hal_status);
        return;
    }
    
    *init_flag = 1;
    log_i("TIM%d Init OK: psc=%d, arr=%d", tim_id == BASE_TIM_ID_TIM6 ? 6 : 7, prescaler, period);
}

/**
 * @brief       基本定时器反初始化
 *
 * @param[in]   tim_id 定时器ID
 *
 * @retval      无
 */
void tim_base_deinit(BASE_TIM_ID_e tim_id)
{
    TIM_HandleTypeDef *handle;
    uint8_t *init_flag;
    
    if (tim_id >= BASE_TIM_ID_MAX)
    {
        log_e("Invalid timer ID: %d", tim_id);
        return;
    }
    
    handle = tim_base_get_handle(tim_id);
    init_flag = tim_base_get_init_flag(tim_id);
    
    if (handle == NULL || init_flag == NULL || !(*init_flag))
    {
        log_w("TIM%d not initialized", tim_id == BASE_TIM_ID_TIM6 ? 6 : 7);
        return;
    }
    
    /* 停止定时器 */
    HAL_TIM_Base_Stop_IT(handle);
    
    /* 禁用中断 */
    if (tim_id == BASE_TIM_ID_TIM6)
    {
#ifdef BASE_TIM_USE_TIM6
        HAL_NVIC_DisableIRQ(TIM6_DAC_IRQn);
#endif
    }
    else if (tim_id == BASE_TIM_ID_TIM7)
    {
#ifdef BASE_TIM_USE_TIM7
        HAL_NVIC_DisableIRQ(TIM7_IRQn);
#endif
    }
    
    /* 反初始化 */
    HAL_TIM_Base_DeInit(handle);
    
    *init_flag = 0;
    log_i("TIM%d DeInit OK", tim_id == BASE_TIM_ID_TIM6 ? 6 : 7);
}

/**
 * @brief       启动基本定时器
 *
 * @param[in]   tim_id 定时器ID
 *
 * @retval      无
 */
void tim_base_start(BASE_TIM_ID_e tim_id)
{
    TIM_HandleTypeDef *handle;
    uint8_t *init_flag;
    
    if (tim_id >= BASE_TIM_ID_MAX)
    {
        log_e("Invalid timer ID: %d", tim_id);
        return;
    }
    
    handle = tim_base_get_handle(tim_id);
    init_flag = tim_base_get_init_flag(tim_id);
    
    if (handle == NULL || init_flag == NULL || !(*init_flag))
    {
        log_e("TIM%d not initialized", tim_id == BASE_TIM_ID_TIM6 ? 6 : 7);
        return;
    }
    
    HAL_TIM_Base_Start_IT(handle);
    log_d("TIM%d started", tim_id == BASE_TIM_ID_TIM6 ? 6 : 7);
}

/**
 * @brief       停止基本定时器
 *
 * @param[in]   tim_id 定时器ID
 *
 * @retval      无
 */
void tim_base_stop(BASE_TIM_ID_e tim_id)
{
    TIM_HandleTypeDef *handle;
    uint8_t *init_flag;
    
    if (tim_id >= BASE_TIM_ID_MAX)
    {
        log_e("Invalid timer ID: %d", tim_id);
        return;
    }
    
    handle = tim_base_get_handle(tim_id);
    init_flag = tim_base_get_init_flag(tim_id);
    
    if (handle == NULL || init_flag == NULL || !(*init_flag))
    {
        log_e("TIM%d not initialized", tim_id == BASE_TIM_ID_TIM6 ? 6 : 7);
        return;
    }
    
    HAL_TIM_Base_Stop_IT(handle);
    log_d("TIM%d stopped", tim_id == BASE_TIM_ID_TIM6 ? 6 : 7);
}

/**
 * @brief       设置定时周期
 *
 * @param[in]   tim_id 定时器ID
 * @param[in]   period_ms 定时周期（ms）
 *
 * @retval      无
 */
void tim_base_set_period(BASE_TIM_ID_e tim_id, uint16_t period_ms)
{
    TIM_HandleTypeDef *handle;
    uint32_t period;
    
    if (tim_id >= BASE_TIM_ID_MAX)
    {
        log_e("Invalid timer ID: %d", tim_id);
        return;
    }
    
    if (period_ms == 0)
    {
        log_e("Invalid period_ms=0");
        return;
    }
    
    handle = tim_base_get_handle(tim_id);
    
    if (handle == NULL)
    {
        return;
    }
    
    /* 计算新周期值（预分频器=7199，计数频率=10kHz） */
    period = period_ms * 10 - 1;
    
    if (period > 65535)
    {
        period = 65535;
    }
    
    __HAL_TIM_SET_AUTORELOAD(handle, period);
}

/**
 * @brief       注册中断回调函数
 *
 * @param[in]   tim_id 定时器ID
 * @param[in]   callback 回调函数指针
 *
 * @retval      无
 */
void tim_base_register_callback(BASE_TIM_ID_e tim_id, void (*callback)(void))
{
    if (tim_id >= BASE_TIM_ID_MAX)
    {
        log_e("Invalid timer ID: %d", tim_id);
        return;
    }
    
    if (callback == NULL)
    {
        log_e("Callback is NULL");
        return;
    }
    
#ifdef BASE_TIM_USE_TIM6
    if (tim_id == BASE_TIM_ID_TIM6)
    {
        s_tim6_callback = callback;
    }
#endif

#ifdef BASE_TIM_USE_TIM7
    if (tim_id == BASE_TIM_ID_TIM7)
    {
        s_tim7_callback = callback;
    }
#endif
}

/**
 * @brief       定时器中断处理函数
 *
 * @param[in]   tim_id 定时器ID
 *
 * @retval      无
 *
 * @note        由HAL_TIM_PeriodElapsedCallback调用
 */
void tim_base_irq_handler(BASE_TIM_ID_e tim_id)
{
    if (tim_id >= BASE_TIM_ID_MAX)
    {
        return;
    }
    
#ifdef BASE_TIM_USE_TIM6
    if (tim_id == BASE_TIM_ID_TIM6 && s_tim6_callback != NULL)
    {
        s_tim6_callback();
    }
#endif

#ifdef BASE_TIM_USE_TIM7
    if (tim_id == BASE_TIM_ID_TIM7 && s_tim7_callback != NULL)
    {
        s_tim7_callback();
    }
#endif
}
